﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;

namespace uk.ac.soton.ses
{
    class Program
    {
        private readonly static string[] _usageStrings = {String.Format("Usage: {0} <command> [options]",System.Reflection.Assembly.GetExecutingAssembly().GetName().Name),
                                                              "Commands:",
                                                              "\tinstall              Installs WSP to a site collection",
                                                              "Install options:",
                                                              "\t/wspfile=filename    Location of WSP file",
                                                              "\t/sitecollection=uri  URI of site collection for deployment"};

        private static void ListFarmFeatureDefinitions(SPFarm farm)
        {
            foreach (SPFeatureDefinition featureDefinition in farm.FeatureDefinitions)
            {
                Console.WriteLine("{0}:{1}", featureDefinition.Id, featureDefinition.DisplayName);
            }
        }
        private static void ListWebFeatures(string webUrl)
        {
            using (SPSite site = new SPSite(webUrl))
            using (SPWeb web = site.OpenWeb())
            {
                foreach (SPFeature feature in web.Features)
                {
                    Console.WriteLine("{0}:{1}", feature.Definition.Id, feature.Definition.DisplayName);
                }
            }
        }

        static void Usage()
        {
            foreach (string s in _usageStrings)
            {
                Console.WriteLine(s);
            }
        }


        private static bool InstallWSP(string wspPath, string siteCollectionUri)
        {
            SPFarm farm = SPFarm.Local;
            Collection<SPWebApplication> webapps = new Collection<SPWebApplication>();
            SPWebApplication webapp = null;
            try
            {
                webapp = SPWebApplication.Lookup(new Uri(siteCollectionUri));
            }
            catch
            {
                Console.WriteLine("...error finding web application at {0}", siteCollectionUri);
                return false;
            }

            if (webapp != null)
            {
                webapps.Add(webapp);

                try
                {
                    Console.WriteLine("...deactivating existing features" + Environment.NewLine);
                    int featuresDeactivated = SharePointDeploymentTools.DeactivateFeature("HDCSharePointToolkit_Feature1", farm);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error deactivating feature");
                    Console.WriteLine(e.Message);
                    return false;
                }

                bool copySuccess = false;
                try
                {
                    Console.WriteLine("...copying solution package" + Environment.NewLine);
                    copySuccess = SharePointDeploymentTools.CopyWSP(wspPath, true, farm, webapps);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error copying solution package");
                    Console.WriteLine(e.Message);
                    return false;
                }

                bool activateSuccess = false;
                if (copySuccess)
                {
                    Console.WriteLine("...activating feature" + Environment.NewLine);
                    activateSuccess = SharePointDeploymentTools.ActivateFeature("HDCSharePointToolkit_Feature1", new Uri(siteCollectionUri), farm);
                }

                //Let's try adding the web.config stuff

                try
                {
                    //Make sure the connectionStrings section is there
                    SPWebConfigModification sectionMod = new SPWebConfigModification();
                    sectionMod.Path = "configuration";
                    sectionMod.Name = "connectionStrings";
                    sectionMod.Value = "<connectionStrings></connectionStrings>";
                    sectionMod.Owner = Assembly.GetExecutingAssembly().FullName;
                    sectionMod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;
                    sectionMod.Sequence = 100;
                    webapp.WebConfigModifications.Add(sectionMod);

                    //Get the configuration settings
                    HDCConfigurationOptions config = HDCConfiguration.GetConfigurationOptions();

                    //Generate and add the new connection string
                    SPWebConfigModification mod = new SPWebConfigModification();
                    mod.Path = "configuration/connectionStrings";
                    mod.Name = String.Format("add[@name='{0}']", "MaterialsMetadataEntities"); //XPath string pointing to <add name='MaterialsMetadataEntities'...> entry
                    mod.Owner = "f1739ef2-181c-4366-bd29-a7f7a84f7adc"; //Unique ID for the setting, so as it should only be removed by this feature
                    mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
                    mod.Value = string.Format(
                        "<add name=\"MaterialsMetadataEntities\" connectionString=\"{0}\" providerName=\"System.Data.EntityClient\" />",
                        config.DatabaseOptions.EntityConnectionString.Replace("\"", "&quot;"));
                    //<add name="MaterialsMetadataEntities" connectionString="metadata=res://*/MaterialsMetadata.csdl|res://*/MaterialsMetadata.ssdl|res://*/MaterialsMetadata.msl;provider=System.Data.SqlClient;provider connection string="Data Source=localhost\sqlexpress;Initial Catalog=MaterialsMetadata9;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient"//
                    //mod.Value = string.Format("<add name=\"{0}\" connectionString=\"metadata=res://*/MaterialsMetadataModel.csdl|res://*/MaterialsMetadataModel.ssdl|res://*/MaterialsMetadataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source={1};Initial Catalog={2};Integrated Security=True;MultipleActiveResultSets=True&quot;\" providerName=\"System.Data.EntityClient\" />",
                    //    "MaterialsMetadataEntities", config.DatabaseOptions.DatabaseServer, config.DatabaseOptions.DatabaseName);

                    //Add change to web.config
                    webapp.WebConfigModifications.Add(mod);
                    //Save web.config changes:
                    webapp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                    //Propogate changes across farm
                    webapp.Update();
                    //---
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error adding web.config entry");
                    Console.WriteLine(e.Message);
                    return false;
                }
                return (copySuccess && activateSuccess);
            }
            else
            {
                Console.WriteLine("...error finding web application at {0}", siteCollectionUri);
                return false;
            }
        }

        static int Main(string[] args)
        {
            string wsppath = "";
            string sitecolluri = "";

            if (args.Length == 0)
            {
                Program.Usage();
                return 1;
            }

            for (int i = 0; i < args.Length; i++)
            {

                string thisArg = args[i];
                Console.WriteLine(thisArg);
                switch (thisArg.ToLower())
                {
                    case "/?":
                    case "/h":
                    case "/help":
                    case "help":
                        Program.Usage();
                        return 0;

                    case "install":
                        //Installing...We need two more arguments for this
                        if (args.Length - 1 < i + 2)
                        {
                            Program.Usage();
                            return 1;
                        }
                        string[] options = { args[i + 1], args[i + 2] };
                        foreach (string s in options)
                        {
                            string [] optParts = s.Split('=');
                            if(optParts.Length!=2)
                            {
                                Program.Usage();
                                return 1;
                            }
                            switch (optParts[0].ToLower())
                            {
                                case "/wspfile":
                                    wsppath = optParts[1];
                                    break;
                                case "/sitecollection":
                                    sitecolluri = optParts[1];
                                    break;
                                default:
                                    Program.Usage();
                                    return 1;
                            }
                        }
                        if(wsppath=="" || sitecolluri=="")
                        {
                            Program.Usage();
                            return 1;
                        }
                        i = i + 2;
                        Console.WriteLine("Installing with options {0} and {1}", wsppath, sitecolluri);
                        bool success = Program.InstallWSP(wsppath, sitecolluri);
                        if (success)
                        {
                            Console.Write("Success.");
                            return 0;
                        }
                        else
                        {
                            return 1;
                        }

                    default:
                        Program.Usage();
                        return 1;
                }

            }
            return 1;


        }
    }
}
